package top.nana7mi.headshot.event;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.monster.EntitySlime;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.translation.I18n;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.event.entity.living.LivingDamageEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import top.nana7mi.headshot.util.HeadShotHandler;

public class HeadShotEventHandler {
    public static float nonProjectileHeadshotMinDistanceSq = 0.5F;

    public static float damageToItemMultiplier = 4.0F;

    public static float damageMultiplier = 4.0F;

    public static float missMultiplier = 1.0F;

    public static boolean playersHaveNoHeads = false;

    private boolean debug = false;
    private int lastHandledEntityId = -1;

    @SubscribeEvent
    public void onLivingHurt(LivingHurtEvent event) {
        if (event.isCanceled()) return;

        float damage = event.getAmount();
        EntityLivingBase victim = event.getEntityLiving();

        String s = EntityList.getEntityString(victim);

        if (s == null)
        {
            s = "generic";
        }

        s = I18n.translateToLocal("entity." + s + ".name");

        this.lastHandledEntityId = victim.getEntityId();
        event.setAmount(recalculateDamage(damage, victim, event.getSource()));
    }

    @SubscribeEvent
    public void onLivingDamage(LivingDamageEvent event) {
        float damage = event.getAmount();
        EntityLivingBase victim = event.getEntityLiving();
        if (this.lastHandledEntityId == victim.getEntityId()) {
            this.lastHandledEntityId = -1;
            return;
        }
        event.setAmount(recalculateDamage(damage, victim, event.getSource()));
    }

    public float recalculateDamage(float damage, EntityLivingBase victim, DamageSource source) {
        World world = victim.world;

        if (world.isRemote || damage < 0.1F || !(world instanceof WorldServer)) {
            return damage;
        }

        Entity projectile = source.getImmediateSource();

        if (projectile == null) {
            return damage;
        }

        Vec3d start = new Vec3d(projectile.posX - projectile.motionX, projectile.posY - projectile.motionY, projectile.posZ - projectile.motionZ);
        Vec3d end = new Vec3d(projectile.posX + projectile.motionX, projectile.posY + projectile.motionY, projectile.posZ + projectile.motionZ);

        if (projectile instanceof net.minecraft.entity.player.EntityPlayer) {
            double d = projectile.getDistanceSq((Entity)victim);
            if (d < nonProjectileHeadshotMinDistanceSq) {
                return damage;
            }
            start = new Vec3d(projectile.posX, projectile.posY + projectile.getEyeHeight(), projectile.posZ);
            Vec3d aim = projectile.getLookVec();
            end = new Vec3d(projectile.posX + aim.x * d, projectile.posY + projectile.getEyeHeight() + aim.y * d, projectile.posZ + aim.z * d);
        }

        if (this.debug)
            for (int i = 20; i < 60; i++) {
                Vec3d iv = start.addVector(projectile.motionX * i * 0.05D, projectile.motionY * i * 0.05D, projectile.motionZ * i * 0.05D);

                // 粒子效果
//                IblisHeadshotsMod.network.spawnHeadshotParticle(victim.world, iv, Vec3d.ZERO, 150);
            }
        if ((!playersHaveNoHeads || !(victim instanceof net.minecraft.entity.player.EntityPlayer)) &&
                HeadShotHandler.traceHeadShot(victim, start, end) != null) {

            // 粒子效果
//            IblisHeadshotsMod.network.spawnHeadshotParticle(victim.world, new Vec3d(victim.posX, victim.posY + victim
//                    .getEyeHeight(), victim.posZ), new Vec3d(0.0D, 0.2D, 0.0D), 15);

            float multiplier = damageMultiplier;
            ItemStack headgear = victim.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
            HashMultimap<String, AttributeModifier> multimap = HashMultimap.create();
            addModifierOfStackInSlot(victim, multimap, EntityEquipmentSlot.CHEST);
            addModifierOfStackInSlot(victim, multimap, EntityEquipmentSlot.LEGS);
            addModifierOfStackInSlot(victim, multimap, EntityEquipmentSlot.FEET);
            if (!multimap.isEmpty()) {
                victim.getAttributeMap().removeAttributeModifiers((Multimap)multimap);
                WorldServer wserver = (WorldServer)world;
                wserver.addScheduledTask(() -> {
                    HashMultimap<String, AttributeModifier> multimap2 = HashMultimap.create();
                    addModifierOfStackInSlot(victim, multimap2, EntityEquipmentSlot.CHEST);
                    addModifierOfStackInSlot(victim, multimap2, EntityEquipmentSlot.LEGS);
                    addModifierOfStackInSlot(victim, multimap2, EntityEquipmentSlot.FEET);
                    victim.getAttributeMap().applyAttributeModifiers((Multimap)multimap2);
                });
            }
            if (!headgear.isEmpty()) {
                // 头盔减少爆头伤害 (大概)
//                float headGearDamageAbsorbMultiplier = IblisItemUtils.getHeadgearProtection(headgear);
//                multiplier = 1.0F + Math.max(multiplier - 1.0F, 0.0F) * headGearDamageAbsorbMultiplier;
//                headgear.damageItem((int)((victim.world.rand.nextFloat() * 0.5D + 1.0D) * damage * damageToItemMultiplier), victim);
            }
            damage *= multiplier;
            Entity shooter = source.getTrueSource();
            if (shooter instanceof EntityPlayerMP && !(victim instanceof EntityPlayerMP)) {
//                HeadshotTrigger.instance.trigger((EntityPlayerMP)shooter, (Entity)victim);
            } else if (victim instanceof EntityPlayerMP) {
//                HeadshotTrigger.instance.trigger((EntityPlayerMP)victim, (Entity)victim);
            }
            if (victim.	getHealth() < damage && victim instanceof EntitySlime && ((EntitySlime)victim)
                    .getSlimeSize() > 1) {
//                ((EntitySlime) victim).setSlimeSize(1, false);
            }
        } else {
            damage *= missMultiplier;
        }
        return damage;
    }

    private void addModifierOfStackInSlot(EntityLivingBase entity, HashMultimap<String, AttributeModifier> multimap, EntityEquipmentSlot slot) {
        ItemStack stack = entity.getItemStackFromSlot(slot);
        if (!stack.isEmpty()) {
            multimap.putAll(stack.getAttributeModifiers(slot));
        }
    }

}
